﻿namespace GDA.Provider.Firebird
{
    using GDA.Provider;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Reflection;
    using FirebirdSql.Data.FirebirdClient;
    using GDA;

    public class FirebirdProvider : GDA.Provider.Provider
    {
        public FirebirdProvider()
            : base("FirebirdProvider", "FirebirdSql.Data.FirebirdClient.dll", "FirebirdSql.Data.FirebirdClient.FbConnection", "FirebirdSql.Data.FirebirdClient.FbDataAdapter", "FirebirdSql.Data.FirebirdClient.FbCommand", "FirebirdSql.Data.FirebirdClient.FbParameter", "@", true, "")
        {
            base.ExecuteCommandsOneAtATime = false;
            Uri uri = new Uri(Assembly.GetExecutingAssembly().EscapedCodeBase);
            base.providerAssembly = Assembly.LoadFrom((uri.IsFile ? Path.GetDirectoryName(uri.LocalPath) : null) + @"\FirebirdSql.Data.FirebirdClient.dll");
        }

        public override long GetDbType(Type type)
        {
            string str;
            FbDbType @decimal = FbDbType.Integer;
            if (type.IsEnum && ((str = Enum.GetUnderlyingType(type).Name) != null))
            {
                if (str == "INTEGER")
                {
                    return 2L;
                }
                if (str == "INTEGER")
                {
                    return 0x1f6L;
                }
                if (str == "INTEGER")
                {
                    return 3L;
                }
                if (str == "INTEGER")
                {
                    return 0x1f7L;
                }
                if (str == "Binary")
                {
                    return 1L;
                }
            }
            if (type.Equals(typeof(int)))
            {
                @decimal = FbDbType.Integer;
            }
            else if (type.Equals(typeof(uint)))
            {
                @decimal = FbDbType.Integer;
            }
            else if (type.Equals(typeof(short)))
            {
                @decimal = FbDbType.Integer;
            }
            else if (type.Equals(typeof(ushort)))
            {
                @decimal = FbDbType.Integer;
            }
            else if (type.Equals(typeof(long)))
            {
                @decimal = FbDbType.Integer;
            }
            else if (type.Equals(typeof(double)) || type.Equals(typeof(float)))
            {
                @decimal = FbDbType.Double;
            }
            else if (type.Equals(typeof(decimal)))
            {
                @decimal = FbDbType.Decimal;
            }
            else if (type.Equals(typeof(DateTime)))
            {
                @decimal = FbDbType.Date;
            }
            else if ((type.Equals(typeof(bool)) || type.Equals(typeof(byte))) || type.Equals(typeof(byte)))
            {
                @decimal = FbDbType.Binary;
            }
            else if (type.Equals(typeof(string)))
            {
                @decimal = FbDbType.VarChar;
            }
            else if (type.Equals(typeof(byte[])) || type.Equals(typeof(byte[])))
            {
                @decimal = FbDbType.Binary;
            }
            return (long)@decimal;
        }

        public override long GetDbType(string dbType, bool isUnsigned)
        {
            switch (dbType)
            {
                case "byte":
                    return 1L;

                case "tinyint":
                    return 1L;

                case "smallint":
                    if (isUnsigned)
                    {
                        return 0x1f6L;
                    }
                    return 2L;

                case "int":
                    if (!isUnsigned)
                    {
                        return 3L;
                    }
                    return 0x1f7L;

                case "bigint":
                    if (!isUnsigned)
                    {
                        return 8L;
                    }
                    return 0x1fcL;

                case "float":
                    return 4L;

                case "datetime":
                    return 12L;

                case "decimal":
                case "numeric":
                    return 0L;

                case "char":
                    return 0xfeL;

                case "varchar":
                    return 0xfdL;

                case "text":
                    return 0xfeL;

                case "tinyblob":
                    return 0xf9L;

                case "blob":
                    return 0xfcL;

                case "mediumblob":
                    return 250L;

                case "longblob":
                    return 0xfbL;

                case "enum":
                    return 0xf7L;
            }
            return -1L;
        }

        public override string QuoteExpression(string word)
        {
            return ("" + word + "");
        }

        public override string SQLCommandLimit(List<Mapper> mapping, string sqlQuery, int startRecord, int size)
        {
            return (sqlQuery + " limit " + startRecord.ToString() + "," + size.ToString());
        }

        public override char QuoteCharacter
        {
            get
            {
                return ' ';
            }
        }

        public override string QuoteExpressionBegin
        {
            get
            {
                return "";
            }
        }

        public override string QuoteExpressionEnd
        {
            get
            {
                return "";
            }
        }

        public override string SqlQueryReturnIdentity
        {
            get
            {
                return "select LAST_INSERT_ID()";
            }
        }

        public override bool SupportSQLCommandLimit
        {
            get
            {
                return true;
            }
        }
    }
}

